import scipy.special
import numpy

class Tree_Designer():
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate, wmode="rand"):
        # 初始化 输入层 隐藏层 输出层 节点数量
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes
        self.lr = learningrate
        # 生成权重矩阵(随机)
        if wmode == "rand":
            self.wih = (numpy.random.rand(self.hnodes,self.inodes) - 0.5)
            self.who = (numpy.random.rand(self.onodes,self.hnodes) - 0.5)
        elif wmode == "normal":
            self.wih = (numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes,self.inodes)) - 0.5)
            self.who = (numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes,self.hnodes)) - 0.5)
        elif wmode[0:3] == "csv" :
            self.wih = numpy.loadtxt(wmode[3:] + "IH.csv")
            self.who = numpy.loadtxt(wmode[3:] + "HO.csv")
        # 定义S函数
        self.activation_function = lambda x: scipy.special.expit(x)
        pass

    def train(self, inputs_list, targets_list):
        inputs = numpy.array(inputs_list, ndmin=2).T
        targets = numpy.array(targets_list, ndmin=2).T
        hidden_inputs = numpy.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        final_inputs = numpy.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        output_errors = targets - final_outputs
        hidden_errors = numpy.dot(self.who.T, output_errors)
        self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
        self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
        pass

    def query(self, inputs_list):
        inputs = numpy.array(inputs_list, ndmin=2).T
        hidden_inputs = numpy.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        final_inputs = numpy.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        return final_outputs
        pass
